package com.gitee.sop.layui.adminserver.module.background.develop.service.impl;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gitee.sop.layui.adminserver.entrance.bo.ServiceContext;
import com.gitee.sop.layui.adminserver.module.background.admin.entity.SysUser;
import com.gitee.sop.layui.adminserver.module.background.admin.service.SysUserFunctionRoleRelationService;
import com.gitee.sop.layui.adminserver.module.background.develop.entity.SysFunctionRole;
import com.gitee.sop.layui.adminserver.module.background.develop.manager.SysFunctionRoleManager;
import com.gitee.sop.layui.adminserver.module.background.develop.mapper.SysFunctionRoleMapper;
import com.gitee.sop.layui.adminserver.module.background.develop.service.SysFunctionRoleRelationService;
import com.gitee.sop.layui.adminserver.module.background.develop.service.SysFunctionRoleService;
import com.gitee.sop.layui.adminserver.module.base.bo.ZTreeNode;
import com.gitee.sop.layui.adminserver.module.base.error.ServiceInterruptionException;
import com.gitee.sop.layui.adminserver.module.base.util.AssertUtil;
import com.gitee.sop.layui.adminserver.module.base.util.NumberCodeGenerator;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author admin
 * @since 2019-11-27
 */
@Service
public class SysFunctionRoleServiceImpl extends ServiceImpl<SysFunctionRoleMapper, SysFunctionRole> implements SysFunctionRoleService {

    @Lazy
    @Resource
    private SysFunctionRoleRelationService sysFunctionRoleRelationService;
    @Lazy
    @Resource
    private SysUserFunctionRoleRelationService sysUserFunctionRoleRelationService;
    @Lazy
    @Resource
    private SysFunctionRoleManager sysFunctionRoleManager;

    @Override
    public boolean updateById(SysFunctionRole entity) {
        SysFunctionRole old = getById(entity.getId());
        AssertUtil.notNull(old, ServiceInterruptionException.fail(400, "更新数据不存在"));
        //状态更新，且更新为禁用状态，将子节点全部更新为禁用状态
        if (!old.getStatus().equals(entity.getStatus()) && entity.getStatus() == 0) {
            String rootCode = NumberCodeGenerator.build().original(old.getCode());
            baseMapper.updateLikeRightCode(rootCode, 0);
        }

        //清空缓存
        this.sysFunctionRoleManager.clearCache();

        return super.updateById(entity);
    }

    @Override
    public void add(SysFunctionRole sysFunctionRole) {

        String code = null;
        NumberCodeGenerator numberCodeGenerator = NumberCodeGenerator.build();
        if (sysFunctionRole.getPid() == 0) {
            SysFunctionRole lastBrother = baseMapper.selectLastOneByPid(0);
            try {
                code = lastBrother == null ? numberCodeGenerator.first() : numberCodeGenerator.next(lastBrother.getCode());
            } catch (Exception e) {
                throw ServiceInterruptionException.fail(500, "功能角色编码不可分配，请联系管理员");
            }
        } else {
            SysFunctionRole parent = checkAndGetParent(sysFunctionRole.getPid());
            SysFunctionRole lastBrother = baseMapper.selectLastOneByPid(parent.getId());
            try {
                code = lastBrother == null ? numberCodeGenerator.child(parent.getCode()) : numberCodeGenerator.next(lastBrother.getCode());
            } catch (Exception e) {
                throw ServiceInterruptionException.fail(500, "功能角色编码不可分配，请联系管理员");
            }
        }
        SysUser cur = ServiceContext.me().checkedUserAndGet(SysUser.class);
        sysFunctionRole.init().setCode(code).setCreatedTime(new Date()).setCreatorUuid(cur.getUuid());
        save(sysFunctionRole);

        //清空缓存
        this.sysFunctionRoleManager.clearCache();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteSelfAndChildrenById(Integer id) {
        SysFunctionRole sysFunctionRole = this.baseMapper.selectById(id);
        if (sysFunctionRole == null) {
            return;
        }
        //通过菜单编号查询所有节点
        String rootCode = NumberCodeGenerator.build().original(sysFunctionRole.getCode());
        //右模糊根编码，即可得到当前编码下所有孩子节点
        List<Integer> idList = baseMapper.selectIdLikeRightCode(rootCode);
        //查询功能角色是否有关联功能
        int count = sysFunctionRoleRelationService.countInFunctionRoleIdList(idList);
        AssertUtil.isFalse(count > 0, ServiceInterruptionException.fail(400, "功能角色或其子角色有关联功能，无法删除"));

        //查询功能角色是否有关联用户
        count = sysUserFunctionRoleRelationService.countInFunctionRoleIdList(idList);
        AssertUtil.isFalse(count > 0, ServiceInterruptionException.fail(400, "功能角色或其子角色有关联用户，无法删除"));

        //删除自身和所有子节点
        removeByIds(idList);

        //清空缓存
        this.sysFunctionRoleManager.clearCache();
    }

    @Override
    public List<SysFunctionRole> getAllParentByCode(List<String> codeList) {
        List<String> parentCodeList = new ArrayList<>(codeList.size());
        NumberCodeGenerator numberCodeGenerator = NumberCodeGenerator.build();
        codeList.forEach(code -> {
            String tempCode = numberCodeGenerator.original(code);
            parentCodeList.addAll(numberCodeGenerator.parentCode(tempCode));
        });
        if (parentCodeList.isEmpty()) {
            return Collections.EMPTY_LIST;
        }
        return this.baseMapper.selectInCodeList(parentCodeList);
    }

    @Override
    public List<String> getFunctionRoleNameListByUserUuid(String userUuid) {
        List<SysFunctionRole> functionRoleList = this.sysFunctionRoleManager.getAllByRelationUserUuid(userUuid, 1);
        if (functionRoleList.isEmpty()) {
            return Collections.EMPTY_LIST;
        }
        //查询角色的所有父角色，子角色拥有父角色的所有权限
        List<String> roleList = new ArrayList<>(functionRoleList.size());
        //整理code
        List<String> codeList = new ArrayList<>(functionRoleList.size());

        functionRoleList.forEach(sysFunctionRole -> {
            //未被禁用角色
            if (sysFunctionRole.isEnable()) {
                //添加当前角色
                roleList.add(sysFunctionRole.getName());
                //有父类才添加code并进行查询
                if (sysFunctionRole.getPid() != 0) {
                    codeList.add(sysFunctionRole.getCode());
                }
            }
        });
        List<SysFunctionRole> parentList = getAllParentByCode(codeList);
        parentList.forEach(sysAdminFunctionRole -> {
            //未被禁用角色
            if (sysAdminFunctionRole.isEnable()) {
                roleList.add(sysAdminFunctionRole.getName());
            }
        });
        return roleList;
    }

    @Override
    public List<ZTreeNode> searchTreeByUserUuid(String userUuid) {
        List<Integer> functionRoleIdList = sysUserFunctionRoleRelationService.getFunctionRoleIdByUserUuid(userUuid);

        SysUser cur = ServiceContext.me().checkedUserAndGet(SysUser.class);
        List<SysFunctionRole> list = baseMapper.selectAllByUserUuid(cur.getUuid(), 1);

        List<ZTreeNode> zTreeNodeList = new ArrayList<>(list.size());
        list.forEach(sysFunctionRole -> {
            ZTreeNode zTreeNode = new ZTreeNode();
            zTreeNode.setName(sysFunctionRole.getName()).setId(sysFunctionRole.getId()).setPId(sysFunctionRole.getPid());
            if (functionRoleIdList.contains(sysFunctionRole.getId())) {
                zTreeNode.setChecked(true).setOpen(true);
            }
            zTreeNodeList.add(zTreeNode);
        });

        zTreeNodeList.add(ZTreeNode.createParent());
        return zTreeNodeList;
    }

    @Override
    public List<SysFunctionRole> getAllByUserUuid(String userUuid) {
        return baseMapper.selectAllByUserUuid(userUuid, null);
    }

    private SysFunctionRole checkAndGetParent(int pid) {
        SysFunctionRole sysFunctionRole = getById(pid);
        AssertUtil.notNull(sysFunctionRole, ServiceInterruptionException.fail(400, "上级角色不存在"));
        return sysFunctionRole;
    }
}
